<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="JJzHX" id="JJzHX"><span data-lake-id="u7f68df50" id="u7f68df50">典型回答</span></h1>
  <p data-lake-id="ue2d78fc4" id="ue2d78fc4"><span data-lake-id="u32e4d112" id="u32e4d112">​</span><br></p>
  <p data-lake-id="ue63eaa8b" id="ue63eaa8b"><span data-lake-id="u32488574" id="u32488574">分库分表，是企业里面比较常见的针对高并发、数据量大的场景下的一种技术优化方案，</span><strong><span data-lake-id="ud7f1a488" id="ud7f1a488">所谓"分库分表"，根本就不是一件事儿，而是三件事儿</span></strong><span data-lake-id="u54cde6bc" id="u54cde6bc">，他们要解决的问题也都不一样。</span></p>
  <p data-lake-id="u6ab2767e" id="u6ab2767e"><strong><span data-lake-id="u80f8f520" id="u80f8f520">​</span></strong><br></p>
  <p data-lake-id="u9b3da678" id="u9b3da678"><span data-lake-id="uc4ea3d6e" id="uc4ea3d6e">这三个事儿分别是"只分库不分表"、"只分表不分库"、以及"既分库又分表"。</span></p>
  <p data-lake-id="uf0927cc5" id="uf0927cc5"><span data-lake-id="uf6923d10" id="uf6923d10">​</span><br></p>
  <p data-lake-id="u19ff1596" id="u19ff1596"><strong><span data-lake-id="uf222c99f" id="uf222c99f">分库主要解决的是并发量大的问题</span></strong><span data-lake-id="u46a35a36" id="u46a35a36">。因为并发量一旦上来了，那么数据库就可能会成为瓶颈，因为数据库的连接数是有限的，虽然可以调整，但是也不是无限调整的。所以，当你的数据库的读或者写的QPS过高，导致你的数据库连接数不足了的时候，就需要考虑分库了，</span><strong><span data-lake-id="u7a29b3a4" id="u7a29b3a4">通过增加数据库实例的方式来提供更多的可用数据库链接，从而提升系统的并发度。</span></strong></p>
  <p data-lake-id="u53ebf945" id="u53ebf945"><strong><span data-lake-id="u21a4e507" id="u21a4e507">​</span></strong><br></p>
  <p data-lake-id="ua2bff06d" id="ua2bff06d"><strong><span data-lake-id="u41c2754b" id="u41c2754b">分表主要解决的是数据量大的问题。</span></strong><span data-lake-id="u9e522b2b" id="u9e522b2b">假如你的单表数据量非常大，因为并发不高，数据量连接可能还够，但是存储和查询的性能遇到了瓶颈了，你做了很多优化之后还是无法提升效率的时候，就需要考虑做分表了。</span></p>
  <p data-lake-id="ud87da878" id="ud87da878"><br></p>
  <p data-lake-id="u4b50a4ef" id="u4b50a4ef"><span data-lake-id="ub4c959f4" id="ub4c959f4">那么，当你的数据库链接也不够了，并且单表数据量也很大导致查询比较慢的时候，就需要做</span><strong><span data-lake-id="ue1e2f7f0" id="ue1e2f7f0">既分库又分表</span></strong><span data-lake-id="ue6f56716" id="ue6f56716">了。</span></p>
  <p data-lake-id="u77e5f4ef" id="u77e5f4ef"><span data-lake-id="ubba2b2aa" id="ubba2b2aa">​</span><br></p>
  <h1 data-lake-id="WhC9L" id="WhC9L"><span data-lake-id="u4bf856d5" id="u4bf856d5">扩展知识</span></h1>
  <p data-lake-id="u4a70886b" id="u4a70886b"><br></p>
  <h2 data-lake-id="PFlJS" id="PFlJS"><span data-lake-id="u45f2cd7f" id="u45f2cd7f">分库、分表、分库分表</span></h2>
  <p data-lake-id="u61a9b447" id="u61a9b447"><br></p>
  <p data-lake-id="uab64a889" id="uab64a889"><strong><span data-lake-id="ufbe16040" id="ufbe16040">分库主要解决的是并发量大的问题</span></strong><span data-lake-id="u284b974b" id="u284b974b">。比较典型的分库的场景就是我们在做微服务拆分的时候，就会按照业务边界，把各个业务的数据从一个单一的数据库中拆分开，分别把订单、物流、商品、会员等数据，分别放到单独的数据库中。</span></p>
  <p data-lake-id="ue90e5b81" id="ue90e5b81"><br></p>
  <p data-lake-id="u356dbc74" id="u356dbc74"><img src="https://www.hollischuang.com/wp-content/uploads/2022/05/16532099518312.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_42%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u3704754e" id="u3704754e"><br></p>
  <p data-lake-id="u251bbec8" id="u251bbec8"><span data-lake-id="u50306506" id="u50306506">还有就是有的时候可能会需要把历史订单挪到历史库里面去。这也是分库的一种具体做法。</span></p>
  <p data-lake-id="u49b99075" id="u49b99075"><br></p>
  <h4 data-lake-id="3a607e91" id="3a607e91"><span data-lake-id="uc45b380e" id="uc45b380e">什么时候分表？</span></h4>
  <p data-lake-id="u141eca5a" id="u141eca5a"><br></p>
  <p data-lake-id="u77b424ef" id="u77b424ef"><strong><span data-lake-id="ua8764352" id="ua8764352">分表主要解决的是数据量大的问题。通过将数据拆分到多张表中，来减少单表的数据量，从而提升查询速度。</span></strong></p>
  <p data-lake-id="u54841b52" id="u54841b52"><br></p>
  <p data-lake-id="u111b80b8" id="u111b80b8"><img src="https://www.hollischuang.com/wp-content/uploads/2022/05/16532100651671.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u56ea3e7d" id="u56ea3e7d"><br></p>
  <p data-lake-id="ue209d3c7" id="ue209d3c7"><span data-lake-id="u21da0931" id="u21da0931">一般我们认为，单表行数超过 500 万行或者单表容量超过 2GB之后，才需要考虑做分库分表了，小于这个数据量，遇到性能问题先建议大家通过其他优化来解决。</span></p>
  <p data-lake-id="udd5dee61" id="udd5dee61"><span data-lake-id="u9268abd2" id="u9268abd2">​</span><br></p>
  <p data-lake-id="u49a5012b" id="u49a5012b"><span data-lake-id="u47dc3f1e" id="u47dc3f1e">PS：以上数据，是阿里巴巴Java开发手册中给出的数据，偏保守，根据实际经验来说，单表抗2000万数据量问题不大，但具体的数据里还是要看记录大小、存储引擎设置、硬件配置等。</span></p>
  <p data-lake-id="ucd33cb51" id="ucd33cb51"><span data-lake-id="u25539431" id="u25539431">​</span><br></p>
  <p data-lake-id="ua5060337" id="ua5060337"><br></p>
  <p data-lake-id="ub344b54d" id="ub344b54d"><span data-lake-id="u300e2a10" id="u300e2a10">那如果，既需要解决并发量大的问题，又需要解决数据量大的问题时候。通常情况下，高并发和数据量大的问题都是同时发生的，所以，我们会经常遇到分库分表需要同时进行的情况。</span></p>
  <p data-lake-id="u14c807c2" id="u14c807c2"><br></p>
  <p data-lake-id="u691496c3" id="u691496c3"><span data-lake-id="uf6ff4aee" id="uf6ff4aee">所以，当你的数据库链接也不够了，并且单表数据量也很大导致查询比较慢的时候，就需要做既分库又分表了。</span></p>
  <p data-lake-id="uce4fa8dc" id="uce4fa8dc"><br></p>
  <h2 data-lake-id="XqsDb" id="XqsDb"><span data-lake-id="uad67fc59" id="uad67fc59">横向拆分和纵向拆分</span></h2>
  <p data-lake-id="ubf2376ad" id="ubf2376ad"><br></p>
  <p data-lake-id="u8a211e98" id="u8a211e98"><span data-lake-id="u632ec057" id="u632ec057">谈及到分库分表，那就要涉及到该如何做拆分的问题。</span></p>
  <p data-lake-id="u5b4a542e" id="u5b4a542e"><br></p>
  <p data-lake-id="u79cd1f41" id="u79cd1f41"><strong><span data-lake-id="u7b01f140" id="u7b01f140">通常在做拆分的时候有两种分法，分别是横向拆分（水平拆分）和纵向拆分(垂直拆分)。</span></strong><span data-lake-id="u5f33386b" id="u5f33386b">假如我们有一张表，如果把这张表中某一条记录的多个字段，拆分到多张表中，这种就是纵向拆分。那如果把一张表中的不同的记录分别放到不同的表中，这种就是横向拆分。</span></p>
  <p data-lake-id="uef96d7ba" id="uef96d7ba"><br></p>
  <p data-lake-id="u16e766f3" id="u16e766f3"><span data-lake-id="u03badac8" id="u03badac8">横向拆分的结果是数据库表中的数据会分散到多张分表中，使得每一个单表中的数据的条数都有所下降。比如我们可以把不同的用户的订单分表拆分放到不同的表中。</span></p>
  <p data-lake-id="uf0bd815c" id="uf0bd815c"><br></p>
  <p data-lake-id="ud9233646" id="ud9233646"><img src="https://www.hollischuang.com/wp-content/uploads/2022/05/16532102470769.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_35%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="uc786d4e2" id="uc786d4e2"><br></p>
  <p data-lake-id="ud5d14b80" id="ud5d14b80"><span data-lake-id="ufcd9ed57" id="ufcd9ed57">纵向拆分的结果是数据库表中的数据的字段数会变少，使得每一个单表中的数据的存储有所下降。比如我可以把商品详情信息、价格信息、库存信息等等分别拆分到不同的表中。</span></p>
  <p data-lake-id="u908ff90b" id="u908ff90b"><br></p>
  <p data-lake-id="u119c9ec5" id="u119c9ec5"><img src="https://www.hollischuang.com/wp-content/uploads/2022/05/16532101898570.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_41%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u09b70e92" id="u09b70e92"><br></p>
  <p data-lake-id="ubcd60ecb" id="ubcd60ecb"><span data-lake-id="u6e889d1e" id="u6e889d1e">还有我们谈到的针对不同的业务做拆分成多个数据库的这种情况，其实也是纵向拆分的一种。</span></p>
  <p data-lake-id="uac6a3261" id="uac6a3261"><br></p>
  <h2 data-lake-id="CL0Df" id="CL0Df"><span data-lake-id="u4285306b" id="u4285306b">分表字段如何选择？</span></h2>
  <p data-lake-id="uc7369006" id="uc7369006"><br></p>
  <p data-lake-id="u058b1b07" id="u058b1b07"><br></p>
  <h2 data-lake-id="HouyD" id="HouyD"><span data-lake-id="u57950ebb" id="u57950ebb">分表算法</span></h2>
  <p data-lake-id="u3d111537" id="u3d111537"><br></p>
  <p data-lake-id="u0d00e9ee" id="u0d00e9ee"><br></p>
  <h2 data-lake-id="d8JQO" id="d8JQO"><span data-lake-id="u13780e40" id="u13780e40">全局ID的生成</span></h2>
  <p data-lake-id="u4ae73dfd" id="u4ae73dfd"><br></p>
  <p data-lake-id="u9f7c6610" id="u9f7c6610"><br></p>
  <h2 data-lake-id="VnSdM" id="VnSdM"><span data-lake-id="ub31ddbd4" id="ub31ddbd4">分库分表的工具</span></h2>
  <p data-lake-id="ub08c4651" id="ub08c4651"><br></p>
  <p data-lake-id="ud503ad89" id="ud503ad89"><span data-lake-id="u1357aa57" id="u1357aa57">在选定了分表字段和分表算法之后，那么，如何把这些功能给实现出来，需要怎么做呢？</span></p>
  <p data-lake-id="u64e1cc35" id="u64e1cc35"><br></p>
  <p data-lake-id="uc5c33403" id="uc5c33403"><span data-lake-id="u3151eaf3" id="u3151eaf3">我们如何可以做到像处理单表一样处理分库分表的数据呢？这就需要用到一个分库分表的工具了。</span></p>
  <p data-lake-id="u8d4dbd77" id="u8d4dbd77"><br></p>
  <p data-lake-id="u7d856cc4" id="u7d856cc4"><span data-lake-id="u1a4fbbb4" id="u1a4fbbb4">目前市面上比较不错的分库分表的开源框架主要有三个，分别是sharding-jdbc、TDDL和Mycat</span></p>
  <p data-lake-id="ua3d83d57" id="ua3d83d57"><br></p>
  <h3 data-lake-id="peYxP" id="peYxP"><span data-lake-id="u015ac5f0" id="u015ac5f0">Sharding-JDBC</span></h3>
  <p data-lake-id="u1e51395e" id="u1e51395e"><br></p>
  <p data-lake-id="ud88f83dd" id="ud88f83dd"><span data-lake-id="uef1641de" id="uef1641de">现在叫ShardingSphere（Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成）。它定位为轻量级Java框架，在Java的JDBC层提供的额外服务。它使用客户端直连数据库，以jar包形式提供服务，无需额外部署和依赖，可理解为增强版的JDBC驱动，完全兼容JDBC和各种ORM框架。</span></p>
  <p data-lake-id="u17b21fd2" id="u17b21fd2"><br></p>
  <p data-lake-id="ufbb99a70" id="ufbb99a70"><span data-lake-id="u9030a79a" id="u9030a79a">开源地址：</span><a href="https://shardingsphere.apache.org" target="_blank" data-lake-id="u2be9cbd8" id="u2be9cbd8"><span data-lake-id="uf16e00f9" id="uf16e00f9">https://shardingsphere.apache.org</span></a></p>
  <p data-lake-id="u19051573" id="u19051573"><br></p>
  <h3 data-lake-id="p3mtf" id="p3mtf"><span data-lake-id="u84aca556" id="u84aca556">TDDL</span></h3>
  <p data-lake-id="u81b01d81" id="u81b01d81"><br></p>
  <p data-lake-id="ucdbdc5f6" id="ucdbdc5f6"><span data-lake-id="u31f440a2" id="u31f440a2">TDDL 是淘宝开源的一个用于访问数据库的中间件， 它集成了分库分表， 读写分离，权重调配，动态数据源配置等功能。封装 jdbc 的 DataSource给用户提供统一的基于客户端的使用。</span></p>
  <p data-lake-id="u04efe793" id="u04efe793"><br></p>
  <p data-lake-id="u4d78812b" id="u4d78812b"><span data-lake-id="uad652eec" id="uad652eec">开源地址：</span><a href="https://github.com/alibaba/tb_tddl" target="_blank" data-lake-id="u45f96d3e" id="u45f96d3e"><span data-lake-id="ub2b89844" id="ub2b89844">https://github.com/alibaba/tb_tddl</span></a></p>
  <p data-lake-id="u1927ee64" id="u1927ee64"><br></p>
  <h3 data-lake-id="c8A6e" id="c8A6e"><span data-lake-id="u4486a7e1" id="u4486a7e1">Mycat</span></h3>
  <p data-lake-id="ua70f6d9b" id="ua70f6d9b"><br></p>
  <p data-lake-id="u08fec9b9" id="u08fec9b9"><span data-lake-id="ue024e7fa" id="ue024e7fa">Mycat是一款分布式关系型数据库中间件。它支持分布式SQL查询，兼容MySQL通信协议，以Java生态支持多种后端数据库，通过数据分片提高数据查询处理能力。</span></p>
  <p data-lake-id="ufbb6c96a" id="ufbb6c96a"><br></p>
  <p data-lake-id="u42f0614b" id="u42f0614b"><span data-lake-id="u81f86b34" id="u81f86b34">开源地址：</span><a href="https://github.com/MyCATApache/Mycat2" target="_blank" data-lake-id="u7cc63a89" id="u7cc63a89"><span data-lake-id="u01f98cc7" id="u01f98cc7">https://github.com/MyCATApache/Mycat2</span></a></p>
 </body>
</html>